package com.chenju.javastatic.adapter;

import com.chenju.javastatic.common.enums.EasyCode;
import com.chenju.javastatic.utils.EasyListUtils;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Type;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class AnnotationVisitorAdapter extends AnnotationVisitor {
    public String simpleName;
    public String desc;
    public List<Object> values;
    public Map<String, Object> valuesMap;

    public boolean isRequestMapping = false;

    public boolean isController = false;
    public boolean isAspect = false;
    public boolean isConfiguration = false;
    public boolean isFeignClient = false;

    public boolean isMapping = false;

    public AnnotationVisitorAdapter(String descriptor) {
        this(589824, descriptor);
        if (this.getClass() != AnnotationVisitorAdapter.class) {
            throw new IllegalStateException();
        }
    }

    public AnnotationVisitorAdapter(int api, String descriptor) {
        super(api);
        this.desc = descriptor;
        this.valuesMap = new HashMap<>();
        setField(descriptor);
    }

    AnnotationVisitorAdapter(List<Object> values) {
        super(589824);
        this.values = values;
    }

    public void visit(String name, Object value) {
        if (this.values == null) {
            this.values = new ArrayList<>(this.desc != null ? 2 : 1);
        }

        if (this.desc != null) {
            this.values.add(name);
        }

        if (value instanceof byte[]) {
            this.values.add(EasyListUtils.asArrayList((byte[])value));
        } else if (value instanceof boolean[]) {
            this.values.add(EasyListUtils.asArrayList((boolean[])value));
        } else if (value instanceof short[]) {
            this.values.add(EasyListUtils.asArrayList((short[])value));
        } else if (value instanceof char[]) {
            this.values.add(EasyListUtils.asArrayList((char[])value));
        } else if (value instanceof int[]) {
            this.values.add(EasyListUtils.asArrayList((int[])value));
        } else if (value instanceof long[]) {
            this.values.add(EasyListUtils.asArrayList((long[])value));
        } else if (value instanceof float[]) {
            this.values.add(EasyListUtils.asArrayList((float[])value));
        } else if (value instanceof double[]) {
            this.values.add(EasyListUtils.asArrayList((double[])value));
        } else {
            this.values.add(value);
        }

    }

    public void visitEnum(String name, String descriptor, String value) {
        if (this.values == null) {
            this.values = new ArrayList<>(this.desc != null ? 2 : 1);
        }

        if (this.desc != null) {
            this.values.add(name);
        }

        this.values.add(new String[]{descriptor, value});
    }

    public AnnotationVisitor visitAnnotation(String name, String descriptor) {
        if (this.values == null) {
            this.values = new ArrayList<>(this.desc != null ? 2 : 1);
        }

        if (this.desc != null) {
            this.values.add(name);
        }

        AnnotationVisitorAdapter annotation = new AnnotationVisitorAdapter(descriptor);
        this.values.add(annotation);
        return annotation;
    }

    public AnnotationVisitor visitArray(String name) {
        if (this.values == null) {
            this.values = new ArrayList<>(this.desc != null ? 2 : 1);
        }

        if (this.desc != null) {
            this.values.add(name);
        }

        List<Object> array = new ArrayList<>();
        this.values.add(array);
        return new AnnotationVisitorAdapter(array);
    }

    public void visitEnd() {
        if (this.desc == null){
            return;
        }
        this.valuesMap = EasyListUtils.toMap(this.values);
        String annotationClassName = Type.getType(this.desc).getClassName();
        if (EasyCode.ANNOTATION_REQUESTMAPPING.equals(annotationClassName)){
            this.isRequestMapping = true;
        }
        if (EasyCode.ANNOTATION_CONTROLLER_LIST.contains(annotationClassName)){
            this.isController = true;
        }
        if (EasyCode.ANNOTATION_ASPECT.equals(annotationClassName)){
            this.isAspect = true;
        }
        if (EasyCode.ANNOTATION_CONFIGURATION.equals(annotationClassName)){
            this.isConfiguration = true;
        }
        if (EasyCode.ANNOTATION_MAPPING_LIST.contains(annotationClassName)){
            this.isMapping = true;
        }
    }

    public void setField(String descriptor) {
        if (descriptor == null) {
            return;
        }
        String[] parts = Type.getType(descriptor).getClassName().split("\\.");
        this.simpleName = parts[parts.length - 1];

        String annotationClassName = Type.getType(this.desc).getClassName();
        if (EasyCode.ANNOTATION_REQUESTMAPPING.equals(annotationClassName)){
            this.isRequestMapping = true;
        }
        if (EasyCode.ANNOTATION_CONTROLLER_LIST.contains(annotationClassName)){
            this.isController = true;
        }
        if (EasyCode.ANNOTATION_ASPECT.equals(annotationClassName)){
            this.isAspect = true;
        }
        if (EasyCode.ANNOTATION_CONFIGURATION.equals(annotationClassName)){
            this.isConfiguration = true;
        }
        if (EasyCode.ANNOTATION_MAPPING_LIST.contains(annotationClassName)){
            this.isMapping = true;
        }
    }
}